#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>

#include <stdlib.h>  // atoi

MYSQL *db = NULL;  // 数据库对象 
MYSQL_STMT *stmt = NULL; // 邓处理语句

void show_err(void){
    printf("error: %s\n", mysql_error(db));
}

void show_err2(const char *title){
    printf("stmt %s error: %s\n", title, mysql_stmt_error(stmt));
}

int connect_db(char *user, char *pwd){
    mysql_library_init(0, NULL, NULL);
    db = mysql_init(NULL);
    if(db == NULL){
        printf("--init fail--\n");
        return -1;
    }

    if(mysql_real_connect(db, "localhost", user, pwd, "cloudfs", 3306, NULL, 0) == NULL){
        show_err();
        return -1;
    }

    return 0;
}

void close_db(){
    if(stmt != NULL)
        mysql_stmt_close(stmt);

    if(db != NULL)
        mysql_close(db);
    mysql_library_end();
}

int query_stmt(char *sql, MYSQL_BIND *binds){
    if(stmt == NULL)
        stmt = mysql_stmt_init(db);
    if(mysql_stmt_prepare(stmt,sql, strlen(sql)) != 0)
    {
        show_err2("prepare");
        return -1;
    }
  
    if(mysql_stmt_bind_param(stmt, binds) != 0){
        show_err2("bind");
        return -1;
    }

    if(mysql_stmt_execute(stmt) != 0){
        show_err2("execute");
        return -1;
    }

    // 获取结果集中的元数据
    MYSQL_RES *res1 = mysql_stmt_result_metadata(stmt);
    int cols = mysql_num_fields(res1);

    unsigned long *lengths = ( unsigned long *) calloc(cols, sizeof(long));
    my_bool *nulls = (my_bool *)calloc(cols , sizeof(my_bool) );
    MYSQL_BIND *results=calloc(cols , sizeof(MYSQL_BIND));

    for(int i=0;i<cols;i++){
        MYSQL_FIELD *f = mysql_fetch_field(res1);
        results[i].buffer_type = f->type;
        results[i].buffer = calloc(1, f->length);
        results[i].buffer_length =  f->length;
        results[i].length = &lengths[i];
        results[i].is_null = &nulls[i];
    }
    
    // 绑定查询结果的字段显示的位置
    if(mysql_stmt_bind_result(stmt, results) != 0){
        show_err2("bind_result");
        return -1;
    }

    // 获取查询结果（一次性的）
    int rows = 0;
    if(mysql_stmt_store_result(stmt) != 0){
        show_err2("store");
        return -1; 
    }else{
        printf("获取结果集OK\n");
        rows = mysql_stmt_num_rows(stmt);
        while(!mysql_stmt_fetch(stmt)){            
            for(int i=0;i<cols;i++){
                if(nulls[i]) {
                    printf("%10s\t", "null");
                    continue;
                }
                if(results[i].buffer_type == MYSQL_TYPE_LONG){
                    printf("%10d\t", *((int *)results[i].buffer));
                }else{
                    printf("%10s\t", (char *)results[i].buffer);
                }
            }
            printf("\n");
        }
    }

    for(int i=0; i<cols; i++){
        free(results[i].buffer);
    }

    free(results);
    free(lengths);
    free(nulls);
    mysql_stmt_free_result(stmt);
    mysql_stmt_reset(stmt);

    return rows;
}

// ./q <page> <page_size>
// 分页查询：   limit (page-1)*page_size, page_size;
int main(int argc, char const *argv[])
{
    if(argc != 3) return -1;
    if(connect_db("root", "root") != 0){
        return -1;
    }
    
    printf("---db connected OK--\n");

    char sql[] = "select * from t_user limit ?,?";
    
    MYSQL_BIND binds[2];
    int page = atoi(argv[1]);
    int page_size = atoi(argv[2]);
    int offset = (page - 1) * page_size;

    binds[0].buffer_type = MYSQL_TYPE_LONG;
    binds[0].buffer = (int *)&offset;
    binds[0].buffer_length = 4;
    binds[0].is_null = 0;

    binds[1].buffer_type = MYSQL_TYPE_LONG;
    binds[1].buffer = (int *)&page_size;
    binds[1].buffer_length = 4;
    binds[1].is_null = 0;

    int ret = query_stmt(sql, binds);
    printf("-----rows(%d)------\n", ret);

    close_db();
    return 0;
}
